package com.itcast.tanhuasso.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itcast.tanhuasso.domain.Soul;
import com.itcast.tanhuasso.domain.User;
import com.itcast.tanhuasso.mapper.SoulMapper;
import com.itcast.tanhuasso.mapper.UserMapper;
import com.itcast.tanhuasso.service.HuanXinService;
import com.itcast.tanhuasso.service.UserService;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;

import javax.tools.Diagnostic;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @PachageName: com.itcast.tanhuasso.service
 * @ClassName:
 * @Description: TODO
 * @Author: Hushi
 * @DateTime: 2021/2/913:29
 * @Version 1.0
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private UserMapper mapper;

    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private HuanXinService huanXinService;

    @Autowired
    private SoulMapper soulMapper;

    @Value("${soul.name1}")
    private String name1;

    @Value("${soul.name2}")
    private String name2;

    @Value("${soul.name3}")
    private String name3;

    @Value("${soul.cover1}")
    private String cover1;

    @Value("${soul.cover2}")
    private String cover2;

    @Value("${soul.cover3}")
    private String cover3;

    @Value("${soul.level1}")
    private String level1;

    @Value("${soul.level2}")
    private String level2;

    @Value("${soul.level3}")
    private String level3;

    @Value("${soul.star1}")
    private String star1;

    @Value("${soul.star2}")
    private String star2;

    @Value("${soul.star3}")
    private String star3;

    @Value("${soul.isLock1}")
    private String isLock1;

    @Value("${soul.isLock2}")
    private String isLock2;

    @Override
    public String login(String phone, String yzm) {
        //获取redis中存储的验证码,比较输入的验证码
        String redisKey = "CHECK_CODE_" + phone;
        String code = redisTemplate.opsForValue().get(redisKey);
        if (!StringUtils.equals(yzm,code)){
            return null;    //错误直接返回
        }
        //正确删除验证码
        redisTemplate.delete(redisKey);

        //校验手机号(新老用户)
        boolean isNew = false;
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("mobile",phone);
        User user = mapper.selectOne(query);
        //****
        String huanxinRedisKey = "huanXinUser";
        if (!this.redisTemplate.hasKey(huanxinRedisKey)){
            this.redisTemplate.opsForList().leftPush(huanxinRedisKey,"abc123");
        }
        //****
        if (user == null){
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));
            mapper.insert(user);
            //环信用户注册
            huanXinService.register(user.getId().longValue());
            //***
            //将此用户添加到redis中
            this.redisTemplate.opsForList().leftPush(huanxinRedisKey,String.valueOf(user.getId()));
            //***
            isNew = true;
        }
        //********************************************************************************************
        //从redis中获取,没有此用户的老用户,将在环信注册(针对测试)
        List<String> range = this.redisTemplate.opsForList().range(huanxinRedisKey, 0, -1);
        if (!range.contains(String.valueOf(user.getId()))){
            huanXinService.register(user.getId().longValue());
            range.add(String.valueOf(user.getId()));
            this.redisTemplate.opsForList().leftPush(huanxinRedisKey,String.valueOf(user.getId()));
        }
        //***************************************************************************************
        //生成token
        Map<String,Object> claims = new HashMap<>();
        claims.put("id",user.getId());

        String token = Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS256, secret)            //设置加密方法和加密盐
                .setExpiration(new DateTime().plusHours(12).toDate())  //token存在12个小时(过期时间)
                .compact();

        //发送消息
        try {
            Map<String,Object> msg = new HashMap<>();
            msg.put("id",user.getId());
            msg.put("date", System.currentTimeMillis());
            rocketMQTemplate.convertAndSend("tanhua-sso-login",msg);

            QueryWrapper<Soul> queryCount = new QueryWrapper<>();
            queryCount.eq("user_id",user.getId());
            Integer count = this.soulMapper.selectCount(queryCount);
            if (count < 1){
                this.soulMapper.insert(new Soul(name1,cover1,level1,star1,Integer.parseInt(isLock1),"",user.getId().longValue()));
                this.soulMapper.insert(new Soul(name2,cover2,level2,star2,Integer.parseInt(isLock2),"",user.getId().longValue()));
                this.soulMapper.insert(new Soul(name3,cover3,level3,star3,Integer.parseInt(isLock2),"",user.getId().longValue()));
            }

        } catch (Exception e) {
            log.error("登录消息发送失败 , " + e);
        }

        return token + "|" + isNew;
    }

    @Override
    public User queryUserByToken(String token) {
        //JWT解析token
        try {
            Map<String,Object> body = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
            User user = new User();
            user.setId(Integer.parseInt(body.get("id").toString()));

            String redisKey = "user_mobile" + user.getId();
            if (this.redisTemplate.hasKey(redisKey)){
                String mobile = this.redisTemplate.opsForValue().get(redisKey);
                user.setMobile(mobile);
            }
            else{
                User user1 = mapper.selectById(user.getId());
                user.setMobile(user1.getMobile());

                long timeOut = Long.valueOf(body.get("exp").toString()) * 1000 - System.currentTimeMillis();
                this.redisTemplate.opsForValue().set(redisKey,user1.getMobile(),timeOut, TimeUnit.MILLISECONDS);
            }
            return user;
        } catch (ExpiredJwtException e) {
            log.info("token已过期!");
        } catch (Exception e) {
            log.error("token不合法!");
        }
        return null;
    }
}
